package org.budo.accesslog.repository.impl;

import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.budo.accesslog.entity.AccesslogEntity;
import org.budo.accesslog.repository.AccesslogRepository;
import org.budo.jdbc.dao.impl.BudoJdbcDaoImpl;
import org.budo.support.dao.page.Page;
import org.budo.support.javax.sql.util.JdbcUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.service.batch.buffered.AbstractBufferedBatchService;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@NoArgsConstructor
@Slf4j
@Getter
@Setter
public class BufferedJdbcAccesslogRepository extends AbstractBufferedBatchService<AccesslogEntity> implements AccesslogRepository {
    private DataSource dataSource;

    public BufferedJdbcAccesslogRepository(DataSource dataSource) {
        this.setDataSource(dataSource);
    }

    @Override
    public List<AccesslogEntity> list(Page page) {
        String sql = "SELECT * FROM t_accesslog ORDER BY id DESC LIMIT ?, ?";
        Object[] parameters = new Object[] { page.getOffset(), null == page.getPageSize() ? 10 : page.getPageSize() };
        return JdbcUtil.executeQuery(this.getDataSource(), sql, parameters, AccesslogEntity.class);
    }

    @Override
    public Integer count() {
        String sql = "SELECT COUNT(*) FROM t_accesslog";
        return JdbcUtil.executeFind(this.getDataSource(), sql, null, Integer.class);
    }

    @Override
    public Integer countByRequestUri(String requestUri) {
        String sql = "SELECT COUNT(*) FROM t_accesslog WHERE request_uri = ?";
        Object[] parameters = new Object[] { requestUri };
        return JdbcUtil.executeFind(this.getDataSource(), sql, parameters, Integer.class);
    }

    @Override
    public void save(AccesslogEntity accesslogEntity) {
        this.addToBuffer(accesslogEntity);
    }

    @Override
    public void flashBuffer(List<AccesslogEntity> bufferCopy) {
        if (null == bufferCopy || bufferCopy.isEmpty()) {
            return;
        }

        if (null == this.getDataSource()) {
            log.error("#60 dataSource is null, this=" + this);
            return;
        }

        String sql = " INSERT INTO t_accesslog ( `request_uri`, `type`, `remote_addr`, `created_at`, `time_cost`, " //
                + " `handler`, `error`, `server_name`, `user_agent`, `remote_user`, `request_body`, `response_body` ) VALUES ";

        List<Object> parameters = new ArrayList<Object>();

        int size = bufferCopy.size();
        for (int i = 0; i < size; i++) {
            AccesslogEntity each = bufferCopy.get(i);

            if (null == each) {
                log.error("#59 flashBuffer, each=" + each + ", bufferCopy=" + bufferCopy);
                continue;
            }

            if (i > 0) {
                sql += " , ";
            }

            sql += " ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) ";

            // 这里的顺序对应着 上面的 INSERT sql
            parameters.add(StringUtil.cutLeft(each.getRequestUri(), 2550));
            parameters.add(each.getType());
            parameters.add(each.getRemoteAddr());
            parameters.add(each.getCreatedAt());
            parameters.add(each.getTimeCost());
            parameters.add(each.getHandler());
            parameters.add(StringUtil.cutLeft(each.getError(), 2550));
            parameters.add(each.getServerName());
            parameters.add(StringUtil.cutLeft(each.getUserAgent(), 2550));
            parameters.add(each.getRemoteUser());

            parameters.add(StringUtil.cutLeft(each.getRequestBody(), 2550));
            parameters.add(StringUtil.cutLeft(each.getResponseBody(), 2550));
        }

        BudoJdbcDaoImpl jdbcDao = new BudoJdbcDaoImpl(this.getDataSource());
        jdbcDao.executeUpdate(sql, parameters.toArray(new Object[parameters.size()]));
    }
}